import React, { PureComponent } from 'react'
import { connect, history } from '@umijs/max'
import {
  Button, Form, Input, message, Modal, Popconfirm, Select, Tooltip, TreeSelect,
} from 'antd'
import list2tree from 'list2tree'
import KeepAlive from 'react-activation'
import {
  HufuTreeTitle,
  InputSearch,
  Logger,
  ProTable,
  ProTableOperate,
  ProTableOptions,
  ProTree,
  searchTreeListByName,
  OSSyncComponentModal,
} from '@/components'
import {
  statistics, online, offline, deleteOffline, runOffline, getDirList, upsetDir, deleteDir, offlineLog, queryUserListReq,
} from './api'
import styles from './index.less'

const getNavTreeDataFunc = list2tree({
  idKey: 'id',
  parentIdKey: 'pid',
  newKey: {
    key: 'id',
    value: 'id',
    title: 'dirName',
  },
})

const { OperateItem } = ProTableOperate
const { Option } = Select
const { Item } = Form

const statusObj = {
  1: {
    key: 1,
    value: '待发布',
    icon: 'icon-daiban',
    color: '#0084FF',
  },
  2: {
    key: 2,
    value: '已发布',
    icon: 'icon-yifabu',
    color: '#43A047',
  },
  // 3: {
  //   key: 3,
  //   value: '未运行',
  //   icon: 'icon-weiyunhang',
  //   color: '#0084FF',
  // },
  // 4: {
  //   key: 4,
  //   value: '运行中',
  //   icon: 'icon-yunhangzhong_1',
  //   color: '#0084FF',
  // },
  // 5: {
  //   key: 5,
  //   value: '成功',
  //   icon: 'icon-chenggong',
  //   color: '#43A047',
  // },
  // 6: {
  //   key: 6,
  //   value: '失败',
  //   icon: 'icon-shibai1',
  //   color: '#EF5350',
  // },
  // 7: {
  //   key: 7,
  //   value: '停止',
  //   icon: 'icon-weiyunhang',
  //   color: '#0084FF',
  // },
}

const statusFilter = () => {
  const arr = []
  for (const k in statusObj) {
    arr.push({
      text: statusObj[k]?.value,
      value: statusObj[k]?.key,
    })
  }
  return arr
}

const scheduleUnitEnum = [
  { value: 0, text: '月' },
  { value: 1, text: '周' },
  { value: 2, text: '天' },
  { value: 3, text: '小时' },
  { value: 4, text: '分钟' },
]

@connect(({ offlineOperation }) => ({ ...offlineOperation }))
class OfflineCenter extends PureComponent {
  constructor(props) {
    super(props)
    this.state = {
      statistic: null,
      query: {
        taskStatus: this.props?.offlineDefaultValue?.[0] || '',
      },
      taskName: '',
      // taskStatus: '',
      treeData: [],
      treeDataNew: [],
      selectedKeys: ['0'],
      loggerList: [],
      tableLoading: false,
      userList: [],
      userId: '',
      filter_taskStatus: this.props?.offlineDefaultValue || [],
      osSyncVisible: false,
      osSynclabel: '',
      osSyncjobid: '',
    }
    this.tableRef = React.createRef()
    this.fileForm = React.createRef()
    this.logger = React.createRef()
    this.time = null
  }

  componentDidMount() {
    this.statistics()
    this.getDirList()
    this.getUserList()
  }

  componentWillUnmount() {
    this.time && clearTimeout(this.time)
  }

  getColumn = () => (
    [
      {
        title: '任务名称',
        dataIndex: 'taskName',
        key: 'taskName',
      },
      {
        title: '源端',
        dataIndex: 'source',
        key: 'source',
      },
      {
        title: '目标端',
        dataIndex: 'target',
        key: 'target',
      },
      {
        title: (
          <span>
            发布状态
            <Tooltip
              placement="top"
              title={
                <div>
                  <p>任务是否发布状态</p>
                </div>
                }
            >
              <i style={{ color: 'rgb(0, 132, 255)' }} className="iconfont icon-yiwentishi" />
            </Tooltip>
          </span>
        ),
        dataIndex: 'taskStatus',
        key: 'taskStatus',
        // defaultFilteredValue: this.props?.offlineDefaultValue || [],
        filters: statusFilter(),
        filteredValue: this.state?.filter_taskStatus,
        // onFilter: (value, record) => record?.taskStatus === value,
        render: (text, record) => text && <span> <i style={{ color: statusObj[text].color }} className={`iconfont ${statusObj[text].icon}`} /> {statusObj[text].value}</span>,
      },
      {
        title: '调度周期',
        dataIndex: 'scheduleUnit',
        key: 'scheduleUnit',
        // filters: scheduleUnitEnum,
        // onFilter: (value, record) => record?.scheduleUnit === value,
        render: (cycle, record) => (
          <span title={record.scheduleInfo} style={{ color: 'rgba(0, 132, 255, 0.85)' }}>
            {scheduleUnitEnum[cycle]?.text}
          </span>
        ),
      },
      {
        title: '发布时间',
        dataIndex: 'publishTime',
        key: 'publishTime',
        sorter: true,
        sortDirections: ['descend', 'ascend'],
      },
      {
        title: '创建人',
        dataIndex: 'creator',
        key: 'creator',
      },
      {
        title: '操作',
        dataIndex: 'action',
        key: 'action',
        fixed: 'right',
        width: 200,
        render: (text, record) => {
          const taskStatus = Number(record.taskStatus)
          const taskRunStatus = Number(record.taskRunStatus)
          return (
            <ProTableOptions>
              <span onClick={() => {
                  history.push(`/dataIntegrate/offline-detail?id=${record.id}`)
                }}
              >查看
              </span>
              {taskStatus !== 2 ? (
                <span onClick={() => {
                  history.push(`/dataIntegrate/offline-create?id=${record.id}`)
                }}
                >编辑
                </span>
              ) : null}
              {taskStatus === 1 ? (
                <span
                  onClick={() => {
                    this.online(record.id)
                  }}
                >发布
                </span>
              ) : null}
              {(taskRunStatus === 4 && taskStatus === 2) || (taskRunStatus === 5 && taskStatus === 2) || (taskRunStatus === 6 && taskStatus === 2) ? (
                <span onClick={() => {
                  this.runOffline(record.id, 0)
                }}
                >重跑
                </span>
              ) : null}
              <span onClick={() => {
                this.runOffline2(record.id, 1)
              }}
              >试运行
              </span>
              {taskStatus !== 1 ? (
                <span onClick={() => {
                  this.offline(record.id)
                }}
                >下线
                </span>
              ) : null}
              <span
                onClick={() => {
                  // history.push(`/dataIntegrate/offline-history?id=${record.id}`)
                  this.linkTo('', record.id)
                }}
              >历史任务
              </span>
              {taskStatus !== 2 ? (
                <Popconfirm title="确定要删除吗？" onConfirm={() => { this.deleteOffline(record.id) }} okText="是" cancelText="否">
                  <span>
                    删除
                  </span>
                </Popconfirm>
              ) : null}
              {process.env.APP_ENV === 'os' ? (
                <span onClick={() => { this.onOSSync(record) }}>
                  同步
                </span>
              ) : null}
            </ProTableOptions>
          )
        },
      },
    ]
  )

  getUserList = () => {
    queryUserListReq().then(res => {
      this.setState({
        userList: res || [],
      })
    })
  }

  statistics = () => {
    statistics().then((data) => {
      this.setState({
        statistic: data,
      })
    })
  }

  onOSSync = (record) => {
    this.setState({
      osSyncVisible: true,
      osSyncjobid: record.id,
      osSynclabel: record.taskName,
    })
  }

  online = (taskId) => {
    const {
      taskName, selectedKeys, taskRunStatus, startTime, endTime, filter_taskStatus,
    } = this.state
    this.setState({
      tableLoading: true,
    })
    online({ taskId }).then((res) => {
      this.setState({
        tableLoading: false,
      })
      if (res.status === 200) {
        this.statistics()
        this.setState({
          query: {
            taskName: taskName || '',
            taskStatus: filter_taskStatus?.[0] || '',
            dirId: selectedKeys[0] || 0,
            taskRunStatus: taskRunStatus || '',
            startTime: startTime || '',
            endTime: endTime || '',
            // taskStatus: this.props?.offlineDefaultValue?.[0] || '',
          },
        })
        message.success(res.msg)
      } else {
        message.error(res.msg)
      }
    })
  }

  offline = (taskId) => {
    const {
      taskName, filter_taskStatus, selectedKeys, taskRunStatus, startTime, endTime,
    } = this.state
    this.setState({ tableLoading: true })
    offline({ taskId }).then((res) => {
      this.setState({ tableLoading: false })
      if (res.status === 200) {
        this.statistics()
        this.setState({
          query: {
            taskName: taskName || '',
            taskStatus: filter_taskStatus?.[0] || '',
            dirId: selectedKeys[0] || 0,
            taskRunStatus: taskRunStatus || '',
            startTime: startTime || '',
            endTime: endTime || '',
          },
        })
        message.success(res.msg)
      } else {
        message.error(res.msg)
      }
    })
  }

  deleteOffline = (id) => {
    const {
      taskName, filter_taskStatus, selectedKeys, taskRunStatus, startTime, endTime,
    } = this.state
    this.setState({ tableLoading: true })
    deleteOffline({ id }).then((res) => {
      this.setState({ tableLoading: false })
      if (res.status === 200) {
        this.statistics()
        this.setState({
          query: {
            taskName: taskName || '',
            taskStatus: filter_taskStatus?.[0] || '',
            dirId: selectedKeys[0] || 0,
            taskRunStatus: taskRunStatus || '',
            startTime: startTime || '',
            endTime: endTime || '',
          },
        })
        message.success(res.msg)
      } else {
        message.error(res.msg)
      }
    })
  }

  runOffline = (taskId, runType) => {
    const {
      taskName, filter_taskStatus, selectedKeys, taskRunStatus, startTime, endTime,
    } = this.state
    this.setState({ tableLoading: true })
    runOffline({ taskId, runType }).then((res) => {
      this.setState({ tableLoading: false })
      this.setState({
        loggerList: [],
      })
      if (res.status === 200) {
        this.statistics()
        this.setState({
          query: {
            taskName: taskName || '',
            taskStatus: filter_taskStatus?.[0] || '',
            dirId: selectedKeys[0] || 0,
            taskRunStatus: taskRunStatus || '',
            startTime: startTime || '',
            endTime: endTime || '',
          },
          // eslint-disable-next-line react/no-unused-state
          id: res.data,
        })
        this.offlineLog(res.data, runType, 0)
        message.success(res.msg)
      } else {
        message.error(res.msg)
      }
    })
  }

  runOffline2 = (taskId, runType) => {
    this.logger.current.iconUpFn()
    this.setState({ tableLoading: true })
    runOffline({ taskId, runType }).then((res) => {
      this.setState({ tableLoading: false })
      this.setState({
        loggerList: [],
      })
      if (res.status === 200) {
        this.statistics()
        this.setState({
          // eslint-disable-next-line react/no-unused-state
          id: res.data,
        })
        this.offlineLog(res.data, runType, 0)
        message.success(res.msg)
      } else {
        message.error(res.msg)
      }
    })
  }

  offlineLog = (logId, runType, offset) => {
    offlineLog({ logId, runType, offset }).then((res) => {
      clearTimeout(this.time)
      if (res.status === 200) {
        if (res.data) {
          if (res.data.logEnd) {
            clearTimeout(this.time)
          } else {
            this.time = setTimeout(() => {
              this.offlineLog(logId, runType, res.data.offset)
            }, 3000)
          }
          let { loggerList } = this.state
          if (res.data.logContent && res.data.logContent.length) {
            loggerList = loggerList.concat(res.data.logContent)
          }
          this.setState({
            loggerList,
          })
        }
      } else {
        clearTimeout(this.time)
      }
    })
  }

  renderTreeNodes = (data) => {
    const tempArr = []
    data.map((item) => {
      const {
        title, children, layerNum, ...restProps
      } = item
      const tempObj = {
        icon: this.defaultIconFun,
        ...restProps,
      }
      tempObj.title = (
        <HufuTreeTitle
          title={title}
          key={item.id}
          icon
          operations={item.id === '0' ? [
            <a
              key={`new${item.id}`}
              onClick={() => this.showModal(item.id)}
            >
              新建目录
            </a>,
          ] : [
            <a
              key={`new${item.id}`}
              onClick={() => this.showModal(item.id)}
            >
              新建目录
            </a>,
            <a
              key={`edit${item.id}`}
              onClick={() => this.onEditClick(item)}
            >
              编辑目录
            </a>,
            <Popconfirm
              title="你确定要删除这个目录吗？"
              okText="确定"
              cancelText="取消"
              onConfirm={() => this.deleteTheme(item)}
              key={`delPop${item.id}`}
            >
              <a
                key={`del${item.id}`}
              >
                删除
              </a>
            </Popconfirm>,
          ]}
        />
      )

      if (item.children) {
        tempObj.children = this.renderTreeNodes(item.children)
      }
      tempArr.push(tempObj)
    })
    return tempArr
  }

  // 打开新建目录弹窗
  showFilesModal = (id) => {
    this.fileForm.current?.resetFields()
    this.setState({
      modifyId: null,
      isShowFiles: true,
    }, () => {
      if (id) {
        this.fileForm.current.setFieldsValue({ pid: id })
      }
    })
  }

  getDirList = () => {
    getDirList().then((res) => {
      this.setState({
        treeData: res.data,
        treeDataNew: getNavTreeDataFunc(res.data || []),
      })
    }, (error) => {
    })
  }

  upsetDir = () => {
    this.fileForm.current.validateFields().then(values => {
      upsetDir({
        ...values,
        id: this.state.modifyId,
      }).then((res) => {
        if (res.status === 200) {
          message.success(res.msg)
          this.getDirList()
          this.setState({
            isShowFiles: false,
          })
        } else {
          message.error(res.msg)
        }
      }, (error) => {
      })
    })
  }

  showModal = (id) => {
    this.fileForm.current?.resetFields()
    this.setState({
      isShowFiles: true,
      modifyId: null,
    }, () => {
      this.fileForm.current.setFieldsValue({
        pid: id,
      })
    })
  }

  onEditClick = (item) => {
    this.setState({
      isShowFiles: true,
      modifyId: item.id,
    }, () => {
      this.fileForm.current.setFieldsValue({
        pid: item.pid,
        dirName: item.title,
      })
    })
  }

  defaultIconFun = props => {
    const { selectedKeys } = this.state
    if (selectedKeys && selectedKeys[0] === props.data.key) {
      return props.expanded ? <i className="iconfont-colour2 icon-wenjianjia-dakaihover" /> : <i className="iconfont-colour2 icon-wenjianjia-morenhover" />
    }
    return props.expanded ? <i className="iconfont-colour2 icon-wenjianjia-dakai" /> : <i className="iconfont-colour2 icon-wenjianjia-moren" />
  }

  // 删除主题
  deleteTheme = (data) => {
    deleteDir({ id: data.id }).then(
      (res) => {
        if (res.status == 200) {
          this.getDirList()
        } else {
          message.warning(res.msg)
        }
      },
      (error) => {
        message.error(error)
      },
    )
  }

  onSelect = (selectedKeys) => {
    this.setState({
      selectedKeys,
      // taskRunStatus: null,
      // taskStatus: null,
      filter_taskStatus: null,
      taskName: null,
      // time: null,
      query: {
        dirId: selectedKeys[0] || 0,
      },
    })
  }

  linkTo = (type, searchValue = '') => {
    const params = searchValue !== '' ? { searchValue } : { filteredDefaultValue: [type] }
    this.props.dispatch({
      type: 'offlineOperation/saveLinkInfo',
      params: {
        ...params,
        operationTabKey: '3',
      },
    })

    history.push('/dataIntegrate/offline/operation')
  }

  handleTableChange = (pagination, filters, sorter) => {
    const queryFilter = {}
    for (const f in filters) {
      if (filters[f]) {
        queryFilter[f] = filters[f].join(',')
      }
      this.setState({ [`filter_${f}`]: filters[f] })
    }

    if (sorter?.order) {
      queryFilter.order = sorter?.order === 'descend' ? 'desc' : 'asc'
      queryFilter.orderField = sorter?.field
    }

    const {
      userId, taskName, selectedKeys,
    } = this.state
    this.tableRef?.current?.resetPageNum()

    const tempQuery = {}
    tempQuery.taskName = taskName || ''
    tempQuery.dirId = selectedKeys?.[0] || 0,
    tempQuery.creatorId = userId || ''

    this.setState({
      query: {
        ...tempQuery,
        ...queryFilter,
      },
    })
  }

  render() {
    const {
      statistic, query, taskName, loggerList, treeData, selectedKeys, isShowFiles, treeDataNew, tableLoading, userList, userId,
      osSyncVisible, osSyncjobid, osSynclabel,
    } = this.state
    return (
      <div className={`${styles.page_content_with_breadcrumb} ${styles.page_content_tabs_height}`}>
        <div className={styles.data_show}>
          <div className={styles.item}>
            <div className={styles.text_overflow_single}><span className={styles.column}>待发布</span> <span className={styles.count}>{statistic && statistic.toReleaseNum}</span></div>
            <i className="iconfont-colour2 icon-yunhangzhong" />
          </div>

          <div className={styles.item} onClick={() => { this.linkTo(5) }}>
            <div className={styles.text_overflow_single}><span className={styles.column}>成功数</span> <span className={styles.count}>{statistic && statistic.successNum}</span></div>
            <i className="iconfont-colour2 icon-chenggong_1" />
          </div>
          <div className={styles.item} onClick={() => { this.linkTo(6) }}>
            <div className={styles.text_overflow_single}><span className={styles.column}>失败数</span> <span className={styles.count}>{statistic && statistic.failNum}</span></div>
            <i className="iconfont-colour2 icon-shibai_1" />
          </div>
          <div className={styles.item} onClick={() => { this.linkTo(4) }}>
            <div className={styles.text_overflow_single}><span className={styles.column}>运行中</span> <span className={styles.count}>{statistic && statistic.runningNum}</span></div>
            <i className="iconfont-colour2 icon-yunhangzhong" />
          </div>
        </div>
        <div className={`${styles.page_content_column} ${styles.page_content_column_ro}`}>
          <div className={styles.data_dev_left}>
            <ProTree
              showLine
              showSearch
              showTitle
              operations={[
                <i
                  key="1"
                  className="iconfont icon-xinjianwenjianjia"
                  title="新建目录"
                  onClick={() => this.showFilesModal()}
                />,
              ]}
              treeData={treeDataNew || []}
              renderTreeNodes={this.renderTreeNodes}
              selectedKeys={selectedKeys}
              onSelect={this.onSelect}
              ref={(dev) => (this.tree = dev)}
              search={(name) => {
                const searchTree = searchTreeListByName(
                  name,
                  treeData,
                  'dirName',
                )
                const treeDataNews = getNavTreeDataFunc(
                  searchTree.result,
                )
                this.setState(
                  {
                    treeDataNew: treeDataNews,
                  },
                  () => {
                    this.tree.onExpand(searchTree.fatchIds)
                  },
                )
              }}
            />
          </div>
          <div className={`${styles.page_content_right} ${styles.page_content_right_flex}`}>
            <div className={styles.offline}>
              <ProTableOperate style={{ marginBottom: 12 }}>
                <OperateItem align="left">
                  <span />
                  <InputSearch
                    placeholder="请输入任务名称进行搜索"
                    value={taskName}
                    onChange={(e) => {
                      this.setState({
                        taskName: e.target.value,
                      })
                    }}
                    onSearch={(e) => {
                      this.tableRef?.current?.resetPageNum()
                      this.setState({
                        query: {
                          taskName: e || '',
                          dirId: selectedKeys[0] || 0,
                          creatorId: userId || '',
                        },
                      })
                    }}
                  />
                </OperateItem>
                <OperateItem>
                  <span>责任人</span>
                  <Select
                    allowClear
                    placeholder="请选择责任人"
                    onChange={(value) => {
                      this.tableRef?.current?.resetPageNum()
                      this.setState({
                        userId: value,
                        query: {
                          taskName: taskName || '',
                          dirId: selectedKeys[0] || 0,
                          creatorId: value || '',
                        },
                      })
                    }}
                  >
                    {
                      userList?.map(item => (
                        <Option key={item.id} value={item.id}>{item.username}</Option>
                      ))
                    }
                  </Select>
                </OperateItem>
                <OperateItem itemType="btn">
                  <Button type="primary" onClick={() => { history.push(`/dataIntegrate/offline-create?dirId=${selectedKeys[0] || 0}`) }}>新建离线任务</Button>
                </OperateItem>
              </ProTableOperate>
              <ProTable
                loading={tableLoading}
                rowKey="id"
                columns={this.getColumn()}
                ref={this.tableRef}
                query={query}
                border={false}
                scroll={{
                  x: 2000,
                }}
                url="/api/v1/integration/offline/page"
                onChange={this.handleTableChange}
              />
            </div>
            <Logger
              list={loggerList || []}
              // hide={hide}
              ref={this.logger}
            />
          </div>
        </div>
        <Modal
          title={this.state.modifyId ? '修改目录' : '新建目录'}
          visible={isShowFiles}
          confirmLoading={this.state.navListSpinning}
          cancelText="取消"
          okText="保存"
          onOk={this.upsetDir}
          onCancel={() => {
            this.setState({
              isShowFiles: false,
              modifyId: null,
            })
          }}
          maskClosable={false}
        >
          <div className={styles.file_box}>
            <Form
              ref={this.fileForm}
              labelCol={{ span: 5 }}
              wrapperCol={{ span: 19 }}
              autoComplete="off"
            >
              <Item
                label="目录名称"
                name="dirName"
                rules={[
                  { required: true, message: '请输入目录名称' },
                ]}
              >
                <Input placeholder="请输入目录名称" />
              </Item>
              <Item
                label="父级目录"
                name="pid"
              >
                <TreeSelect
                  allowClear
                  showSearch
                  getPopupContainer={(triggerNode) => triggerNode.parentNode}
                  // dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
                  treeData={getNavTreeDataFunc(treeData || [])}
                  placeholder="请选择父级目录"
                  treeDefaultExpandAll
                  filterTreeNode={(input, treeNode) => treeNode.name.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                  fieldNames={{
                    label: 'dirName', value: 'id', children: 'children',
                  }}
                />
              </Item>
            </Form>
          </div>
        </Modal>
        <OSSyncComponentModal
          visible={osSyncVisible}
          onClose={() => this.setState({ osSyncVisible: false })}
          jobtype="1"
          jobid={osSyncjobid}
          label={osSynclabel}
        />
      </div>
      // </KeepAlive>
    )
  }
}

export default class Offline extends PureComponent {
  render() {
    return (
      <KeepAlive
        saveScrollPosition="screen"
        when={() => {
          if (history.location.pathname === '/dataIntegrate/offline-history' || history.location.pathname === '/dataIntegrate/offline-detail') {
            return true
          }
          return false
        }}
        cacheKey="UNIQUE_ID"
      ><OfflineCenter />
      </KeepAlive>
    )
  }
}
